#pragma once

#include "base/Macro.hpp"
#include "core/page/Page.hpp"

class FileCommon {
public:

    static int writePage(std::fstream& file, uint64_t pageNo,std::vector<uint8_t> &page){
//        seekg 用于读，写应该用 seekp
        if (page.size() != PAGE_SIZE){
            std::cerr << "page size error" << std::endl;
            return -1;
        }
        file.seekp(pageNo * PAGE_SIZE);
        file.write(reinterpret_cast<const char*>(page.data()), PAGE_SIZE);
        return file.good() ? 0 : -1;
    }

    static int readPage(std::fstream& file, uint64_t pageNo,std::vector<uint8_t> &page){
        file.seekg(pageNo * PAGE_SIZE);
        file.read(reinterpret_cast<char*>(page.data()), PAGE_SIZE);
        return file.good() ? 0 : -1;
    }


    static int readTableFileHeader(std::fstream &inFile,FileHeader &fileHeader){
        std::vector<uint8_t> page(PAGE_SIZE);
        int ret =FileCommon::readPage(inFile,FILE_HEADER_NO,page);
        if(ret != 0){
            std::cerr << "readTableFileHeader is error " << std::endl;
        }
        memcpy(&fileHeader, page.data(), FILE_HEADER_SIZE);
        return ret;
    };

    static int readTableFieldList(std::fstream &inFile,std::vector<FieldInfo> &fieldList){
        std::vector<uint8_t> page(PAGE_SIZE);
        int ret = FileCommon::readPage(inFile,SCHEMA_PAGE_NO,page);
        if(ret != 0){
            std::cerr << "readTableFieldList is error " << std::endl;
            return ret;
        }
        size_t count = fieldList.size();
        fieldList.clear();

        for(size_t i = 0;i<count;++i){
            FieldInfo fi{};
            std::memcpy(&fi, page.data() + i * sizeof(FieldInfo), sizeof(FieldInfo));
            fieldList.push_back(fi);
        }
//    memcpy(&fieldList, page.data(), fieldList.size() * sizeof(FieldInfo));
        return ret;
    };

    static int saveFileHeader(std::fstream &file,FileHeader &fileHeader){
        std::vector<uint8_t> page(PAGE_SIZE);
        memcpy(page.data(),&fileHeader,FILE_HEADER_SIZE);

        int ret = FileCommon::writePage(file,FILE_HEADER_NO,page);
        if(ret != 0){
            std::cerr << "writePage is error " << std::endl;
        }
        return ret;
    }

    static uint32_t orderWrite(std::fstream &file,std::vector<uint8_t> &row){
        uint32_t offset = static_cast<uint32_t>(file.tellp());
        file.write(reinterpret_cast<const char*>(row.data()), row.size());
        if(file.good() == 0){
            return offset;
        }else{
            return -1;
        }
    }
//    static int savePageHeader(std::fstream &file,PageHead &pageHead){
//        std::vector<uint8_t> page(PAGE_SIZE);
//        memcpy(page.data(),&pageHead,PAGE_HEAD_SIZE);
//
//        int ret = FileCommon::writePage(file,FILE_HEADER_NO,page);
//        if(ret != 0){
//            std::cerr << "writePage is error " << std::endl;
//        }
//        return ret;
//    }




























    template<typename T>
    static void writeStruct(std::fstream& file, const T& data, std::streamoff position,uint32_t size = 0) {
        file.seekp(position);
        if(size == 0){
            size = sizeof(data);
        }
        file.write(reinterpret_cast<const char*>(&data), size);
    }

    template<typename T>
    static bool readFileStruct(std::fstream& inFile, T& result,std::streamoff position,uint32_t endPos) {
        if (!inFile.is_open()) {
            std::cerr << "文件未打开" << std::endl;
            return false;
        }
        // 检查位置是否有效
        if (position < 0) {
            std::cerr << "位置无效" << std::endl;
            return false;
        }
        inFile.seekg(position);
        return inFile.read(reinterpret_cast<char*>(&result), endPos).good();
    }


    template<typename T>
    static bool readFileStruct(std::fstream& inFile, std::vector<T>& result, std::streamoff position, uint32_t size=0) {
        if (!inFile.is_open()) {
            std::cerr << "文件未打开" << std::endl;
            return false;
        }
        if (position < 0) {
            std::cerr << "位置无效" << std::endl;
            return false;
        }

        inFile.seekg(position);
        if(size == 0){
            size = sizeof(T);
        }
        for (size_t i = 0; i < result.size(); i++) {
            if (!inFile.read(reinterpret_cast<char*>(&result[i]), size)) {
                std::cerr << "Failed to read element " << i << std::endl;
                return false;
            }
        }
        return true;
    }

};